package com.taysear.bus;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.taysear.bus.util.Constants;
import com.taysear.bus.util.Results;
import com.taysear.bus.util.Util;
import com.taysear.bus.util.Constants.SysConfig;
import com.taysear.bus.util.vaadin.SmartBeanContainer;
import com.taysear.dbservice.DbServicesPrx;
import com.taysear.dbservice.ServiceParameter;
import com.taysear.dbservice.ServiceResult;
import com.taysear.domain.Route;
import com.taysear.domain.Seat;
import com.taysear.domain.Substation;
import com.taysear.domain.Time;
import com.taysear.domain.helper.Temp;
import com.vaadin.data.Container;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.data.util.BeanContainer;
import com.vaadin.data.util.BeanItem;
import com.vaadin.data.validator.StringLengthValidator;
import com.vaadin.event.DataBoundTransferable;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
import com.vaadin.event.dd.acceptcriteria.And;
import com.vaadin.event.dd.acceptcriteria.ClientSideCriterion;
import com.vaadin.event.dd.acceptcriteria.SourceIs;
import com.vaadin.ui.Button;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomLayout;
import com.vaadin.ui.Field;
import com.vaadin.ui.Form;
import com.vaadin.ui.FormFieldFactory;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.OptionGroup;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;
import com.vaadin.ui.Tree;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.themes.Runo;

@SuppressWarnings("serial")
public class SystemSettingsView extends HorizontalLayout {

	Tree navTree = new Tree();
	HorizontalLayout actionButtons = new HorizontalLayout();
	Button routeDetailsBtn = new Button("Route details");
	Button routeTimesBtn = new Button("Route times");
	Table table = new Table();
	
	Boolean isSaved = false;
	
	public SystemSettingsView() {
		setSpacing(true);
		
		navTree.setSelectable(true);
		navTree.setNullSelectionAllowed(false);
		navTree.setImmediate(true);
		
		BeanContainer<Integer, SysConfig> container = new BeanContainer<Integer, SysConfig>(SysConfig.class);
		for (SysConfig config : SysConfig.getList()) {
			container.addItem(config.getId(), config);
		}
		
		navTree.setContainerDataSource(container);
		navTree.setItemCaptionPropertyId("description");
		
		for (Object id : navTree.getItemIds()) {
			navTree.setChildrenAllowed(id, false);
		}
		
		// select first entity view
		//navTree.setValue(navTree.getItemIds().iterator().next());
		navTree.addListener(new Property.ValueChangeListener() {
			@Override
			public void valueChange(ValueChangeEvent event) {
				if(event.getProperty().getValue() != null) {
					isSaved = false;
					routeDetailsBtn.setVisible(false);
					routeTimesBtn.setVisible(false);
					
					SysConfig config = ((BeanItem<SysConfig>) navTree.getContainerDataSource().getItem(navTree.getValue())).getBean();
					if(config.getId() == SysConfig.TIME.getId()) {
						loadTimeData();
					} else if(config.getId() == SysConfig.ROUTE.getId()) {
						loadRouteData();
						routeDetailsBtn.setVisible(true);
						routeTimesBtn.setVisible(true);
					} else if(config.getId() == SysConfig.SEAT.getId()) {
						loadSeatData();
					} else {
						table.setVisible(false);
						actionButtons.setVisible(false);
					}
				}
			}
		});
		addComponent(navTree);

		CustomLayout manageSysSettingLayout = new CustomLayout("manageSystemSettings");
		
		actionButtons.setVisible(false);
		actionButtons.setSpacing(true);
		
		final Button addBtn = new Button("Add");
		addBtn.addStyleName("greenButton");
		addBtn.setDisableOnClick(true);
		addBtn.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	SysConfig config = ((BeanItem<SysConfig>) navTree.getContainerDataSource().getItem(navTree.getValue())).getBean();
		    	if(config.getId() == SysConfig.TIME.getId()) {
					displayAddTime(SysConfig.TIME.getDescription());
				} else if(config.getId() == SysConfig.ROUTE.getId()) {
					displayAddRoute(SysConfig.ROUTE.getDescription());
				} else if(config.getId() == SysConfig.SEAT.getId()) {
					displayAddSeat(SysConfig.SEAT.getDescription());
				} 
		    	event.getButton().setEnabled(true);
		    }
		});
		actionButtons.addComponent(addBtn);
		
		final Button editBtn = new Button("Edit");
		editBtn.addStyleName("greenButton");
		editBtn.setEnabled(false);
		editBtn.setDisableOnClick(true);
		editBtn.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	SysConfig config = ((BeanItem<SysConfig>) navTree.getContainerDataSource().getItem(navTree.getValue())).getBean();
				if(config.getId() == SysConfig.TIME.getId()) {
					displayEditTime(SysConfig.TIME.getDescription());
				} else if(config.getId() == SysConfig.ROUTE.getId()) {
					displayEditRoute(SysConfig.ROUTE.getDescription());
				} else if(config.getId() == SysConfig.SEAT.getId()) {
					displayEditSeat(SysConfig.SEAT.getDescription());
				}
		    	event.getButton().setEnabled(true);
		    }
		});
		actionButtons.addComponent(editBtn);
		
		routeDetailsBtn.setVisible(false);
		routeDetailsBtn.setEnabled(false);
		routeDetailsBtn.addStyleName("blueButton");
		routeDetailsBtn.setDisableOnClick(true);
		routeDetailsBtn.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	displayRouteDetails();
		    	event.getButton().setEnabled(true);
		    }
		});
		actionButtons.addComponent(routeDetailsBtn);
		
		routeTimesBtn.setVisible(false);
		routeTimesBtn.setEnabled(false);
		routeTimesBtn.addStyleName("blueButton");
		routeTimesBtn.setDisableOnClick(true);
		routeTimesBtn.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	displayRouteTimes();
		    	event.getButton().setEnabled(true);
		    }
		});
		actionButtons.addComponent(routeTimesBtn);

		table.addStyleName(Runo.TABLE_SMALL);
		table.setVisible(false);
		table.setSelectable(true);
		table.setPageLength(Constants.PAGE_SIZE);
		table.setImmediate(true);
		table.setWidth("760px");
		table.addListener(new ValueChangeListener() {
			@Override
			public void valueChange(ValueChangeEvent event) {
				SysConfig config = ((BeanItem<SysConfig>) navTree.getContainerDataSource().getItem(navTree.getValue())).getBean();
				if(event.getProperty().getValue() != null) {
					editBtn.setEnabled(true);
					if(config.getId() == SysConfig.ROUTE.getId()) {
						routeDetailsBtn.setEnabled(true);
						routeTimesBtn.setEnabled(true);
					}
				} else {
					editBtn.setEnabled(false);
					routeDetailsBtn.setEnabled(false);
					routeTimesBtn.setEnabled(false);
				}
			}
		});
		
		manageSysSettingLayout.addComponent(actionButtons, "actionButtons");
		manageSysSettingLayout.addComponent(table, "result");
		addComponent(manageSysSettingLayout);
	}
	
	/**
	 * Creates the window used for editing and adding.
	 * 
	 * @param caption
	 */
	private Window createWindow(String caption) {
		Window window = new Window(caption);
    	
		window.center();
    	window.setModal(true);
    	
    	return window;
	}
	
	/**
	 * Displays the data from times table in a table view.
	 */
	private void loadTimeData() {
		BusApplication app = AppData.getApp();
		ServiceParameter sp = new ServiceParameter(new HashMap<String, String>());
		
		BeanContainer<Integer, Time> container = new BeanContainer<Integer, Time>(Time.class);
		container.setBeanIdProperty("timeId");
		
		DbServicesPrx dbServicesPrx = app.getDbServiceProxy();
		ServiceResult sr = dbServicesPrx.getTimes(sp);
		if(sr.status) {
			if(sr.param.get("RECORDS") != null) {
				Results r = Util.getObjectsFromXmlResult(sr.param.get("RECORDS"), Time.class);
				for (Object object : r.getRows()) {
					Time o = (Time) object;
					container.addItem(o.getTimeId(), o);
				}
				table.setContainerDataSource(container);
				table.setVisible(true);
				actionButtons.setVisible(true);
				table.setVisibleColumns(Constants.columnsTimeTable);
			} else {
				table.setContainerDataSource(null);
				table.setVisible(false);
				actionButtons.setVisible(false);
			}
		} else {
			app.showErrorNotification(sr.message);
			table.setContainerDataSource(null);
			table.setVisible(false);
			actionButtons.setVisible(false);
		}
	}
	
	/**
	 * Displays a popup to add a new time.
	 */
	private void displayAddTime(String description) {
		Window window = createWindow("Add "+ description);
    	
		final Form form = new Form();
    	form.setWidth("500px");
		form.setFormFieldFactory(new FormFieldFactory() {
			
			@Override
			public Field createField(Item item, Object propertyId, Component uiContext) {
				Field f = null;
				if ("reportingTime".equals(propertyId)) {
					TextField field = new TextField("Reporting time");
					field.focus();
					field.setRequired(true);
					field.setImmediate(true);
					field.setWidth(Constants.COMMON_FIELD_WIDTH_M);
					field.setRequiredError(Constants.ME_FIELDS_REQUIRED);
					field.setNullRepresentation("");
					return field;
				} if ("departureTime".equals(propertyId)) {
					TextField field = new TextField("Departure time");
					field.setRequired(true);
					field.setImmediate(true);
					field.setWidth(Constants.COMMON_FIELD_WIDTH_M);
					field.setRequiredError(Constants.ME_FIELDS_REQUIRED);
					field.setNullRepresentation("");
					return field;
				} if ("ampm".equals(propertyId)) {
					ComboBox field = new ComboBox("AM PM");
					field.setRequired(true);
					field.setImmediate(true);
					field.setWidth(Constants.COMMON_FIELD_WIDTH_M);
					field.setRequiredError(Constants.ME_FIELDS_REQUIRED);
					field.setNullSelectionAllowed(false);
					
					BeanContainer<String, Temp> container = new BeanContainer<String, Temp>(Temp.class);
					container.addItem("AM", new Temp(1, "AM"));
					container.addItem("PM", new Temp(1, "PM"));
					field.setContainerDataSource(container);
					field.setItemCaptionPropertyId("description");
					
					return field;
				} 
				return f;
			}
		});
		form.setItemDataSource(new BeanItem<Time>(new Time()));
		form.setVisibleItemProperties(Constants.columnsTimeForm);
		
		Button close = Util.getCloseButton(window);
		close.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	if(isSaved)
		    		loadTimeData();
		    }
		});
		
		Button save = new Button("Save");
		save.addStyleName("blueButton");
		save.setDisableOnClick(true);
		save.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	BusApplication app = (BusApplication) getApplication();
		    	if(form.isValid()) {
		    		Temp ampm = ((BeanItem<Temp>)((ComboBox)form.getField("ampm")).getContainerDataSource().getItem(form.getField("ampm").getValue())).getBean();
		    		ServiceParameter sp = new ServiceParameter(new HashMap<String, String>());
		    		sp.param.put("userId", AppData.getUser().getUserId().toString());
		    		sp.param.put("reportingTime", form.getField("reportingTime").getValue().toString());
		    		sp.param.put("departureTime", form.getField("departureTime").getValue().toString());
		    		sp.param.put("ampm", ampm.getDescription());
		    		
		    		DbServicesPrx dbServicesPrx = app.getDbServiceProxy();
		    		ServiceResult sr = dbServicesPrx.addTime(sp);
		    		
		    		if(sr.status) {
		    			form.setReadOnly(true);
		    			app.showNotification(Constants.MN_SUCCESSFULLY_SAVED);
		    			event.getButton().setEnabled(false);
		    			isSaved = true;
		    		} else {
		    			app.showErrorNotification(sr.message);
		    			event.getButton().setEnabled(true);
		    			isSaved = false;
		    		}
		    	} else {
		    		app.showErrorNotification(Constants.ME_FORM_FIELDS_REQUIRED);
		    		event.getButton().setEnabled(true);
		    	}
		    }
		});
		
		HorizontalLayout buttons = new HorizontalLayout();
		buttons.setSpacing(true);
		buttons.addComponent(save);
		buttons.addComponent(close);
    	
		VerticalLayout verticalLayout = (VerticalLayout) window.getContent();
		verticalLayout.setMargin(true);
        verticalLayout.setSpacing(true);
		verticalLayout.setSizeUndefined();
		verticalLayout.addComponent(form);
		verticalLayout.addComponent(buttons);
    	getApplication().getMainWindow().addWindow(window);
	}
	
	/**
	 * Displays a popup to edit the selected time.
	 */
	private void displayEditTime(String description) {
		Window window = createWindow("Edit "+ description);
    	
		final Form form = new Form();
    	form.setWidth("500px");
		form.setFormFieldFactory(new FormFieldFactory() {
			
			@Override
			public Field createField(Item item, Object propertyId, Component uiContext) {
				Field f = null;
				if ("timeId".equals(propertyId)) {
					TextField field = new TextField("Time id");
					field.setRequired(true);
					field.setImmediate(true);
					field.setWidth(Constants.COMMON_FIELD_WIDTH_M);
					field.setRequiredError(Constants.ME_FIELDS_REQUIRED);
					field.setNullRepresentation("");
					field.setReadOnly(true);
					return field;
				} if ("reportingTime".equals(propertyId)) {
					TextField field = new TextField("Reporting time");
					field.focus();
					field.setRequired(true);
					field.setImmediate(true);
					field.setWidth(Constants.COMMON_FIELD_WIDTH_M);
					field.setRequiredError(Constants.ME_FIELDS_REQUIRED);
					field.setNullRepresentation("");
					return field;
				} if ("departureTime".equals(propertyId)) {
					TextField field = new TextField("Departure time");
					field.setRequired(true);
					field.setImmediate(true);
					field.setWidth(Constants.COMMON_FIELD_WIDTH_M);
					field.setRequiredError(Constants.ME_FIELDS_REQUIRED);
					field.setNullRepresentation("");
					return field;
				} if ("ampm".equals(propertyId)) {
					ComboBox field = new ComboBox("AM PM");
					field.setRequired(true);
					field.setImmediate(true);
					field.setWidth(Constants.COMMON_FIELD_WIDTH_M);
					field.setRequiredError(Constants.ME_FIELDS_REQUIRED);
					field.setNullSelectionAllowed(false);
					
					BeanContainer<String, Temp> container = new BeanContainer<String, Temp>(Temp.class);
					container.addItem("AM", new Temp(1, "AM"));
					container.addItem("PM", new Temp(2, "PM"));
					field.setContainerDataSource(container);
					field.setItemCaptionPropertyId("description");
					
					return field;
				} 
				return f;
			}
		});
		form.setItemDataSource(table.getItem(table.getValue()));
		form.setVisibleItemProperties(Constants.columnsTimeTable);
		
		Button close = Util.getCloseButton(window);
		close.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	if(isSaved)
		    		loadTimeData();
		    }
		});
		
		Button save = new Button("Save");
		save.addStyleName("blueButton");
		save.setDisableOnClick(true);
		save.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	BusApplication app = (BusApplication) getApplication();
		    	if(form.isValid()) {
		    		Temp ampm = ((BeanItem<Temp>)((ComboBox)form.getField("ampm")).getContainerDataSource().getItem(form.getField("ampm").getValue())).getBean();
		    		ServiceParameter sp = new ServiceParameter(new HashMap<String, String>());
		    		sp.param.put("userId", AppData.getUser().getUserId().toString());
		    		sp.param.put("timeId", form.getField("timeId").getValue().toString());
		    		sp.param.put("reportingTime", form.getField("reportingTime").getValue().toString());
		    		sp.param.put("departureTime", form.getField("departureTime").getValue().toString());
		    		sp.param.put("ampm", ampm.getDescription());
		    		
		    		DbServicesPrx dbServicesPrx = app.getDbServiceProxy();
		    		ServiceResult sr = dbServicesPrx.editTime(sp);
		    		
		    		if(sr.status) {
		    			form.setReadOnly(true);
		    			app.showNotification(Constants.MN_SUCCESSFULLY_SAVED);
		    			event.getButton().setEnabled(false);
		    			isSaved = true;
		    		} else {
		    			app.showErrorNotification(sr.message);
		    			event.getButton().setEnabled(true);
		    			isSaved = false;
		    		}
		    	} else {
		    		app.showErrorNotification(Constants.ME_FORM_FIELDS_REQUIRED);
		    		event.getButton().setEnabled(true);
		    	}
		    }
		});
		
		HorizontalLayout buttons = new HorizontalLayout();
		buttons.setSpacing(true);
		buttons.addComponent(save);
		buttons.addComponent(close);
    	
		VerticalLayout verticalLayout = (VerticalLayout) window.getContent();
		verticalLayout.setMargin(true);
        verticalLayout.setSpacing(true);
		verticalLayout.setSizeUndefined();
		verticalLayout.addComponent(form);
		verticalLayout.addComponent(buttons);
    	getApplication().getMainWindow().addWindow(window);
	}
	
	/**
	 * Displays the data from route table in a table view.
	 */
	private void loadRouteData() {
		BusApplication app = AppData.getApp();
		ServiceParameter sp = new ServiceParameter(new HashMap<String, String>());
		
		BeanContainer<Integer, Route> container = new BeanContainer<Integer, Route>(Route.class);
		container.setBeanIdProperty("routeId");
		
		DbServicesPrx dbServicesPrx = app.getDbServiceProxy();
		ServiceResult sr = dbServicesPrx.getRoutes(sp);
		if(sr.status) {
			if(sr.param.get("RECORDS") != null) {
				Results r = Util.getObjectsFromXmlResult(sr.param.get("RECORDS"), Route.class);
				for (Object object : r.getRows()) {
					Route o = (Route) object;
					container.addItem(o.getRouteId(), o);
				}
				table.setContainerDataSource(container);
				table.setVisible(true);
				actionButtons.setVisible(true);
				table.setVisibleColumns(Constants.columnsRouteTable);
			} else {
				table.setContainerDataSource(null);
				table.setVisible(false);
				actionButtons.setVisible(false);
			}
		} else {
			app.showErrorNotification(sr.message);
			table.setContainerDataSource(null);
			table.setVisible(false);
			actionButtons.setVisible(false);
		}
	}
	
	/**
	 * Creates a popup that is used to display the route times, and modify if needed. 
	 */
	private void displayRouteTimes() {
		Window window = createWindow("Route times");

		final BusApplication app = AppData.getApp();
		
		final ServiceParameter sp = new ServiceParameter(new HashMap<String, String>());
		sp.param.put("userId", AppData.getUser().getUserId().toString());
		sp.param.put("routeId", table.getValue().toString());
		sp.param.put("getAvailable", new Boolean(true).toString());
		
		final Map<String, String> routeTimesResult = getRouteTimes(sp);
		
		BeanContainer<Integer, Time> timesContainer = new BeanContainer<Integer, Time>(Time.class);
		timesContainer.setBeanIdProperty("timeId");
		
		final OptionGroup routeTimesOptionGroup = new OptionGroup();
		routeTimesOptionGroup.setMultiSelect(true);
		
		final Set<Object> selectedTimes = new HashSet<Object>();
		
		if(Util.isNotEmptyResult(routeTimesResult.get("RECORDS"))) {
			Results r = Util.getObjectsFromXmlResult(routeTimesResult.get("RECORDS"), Time.class);
			for (Object object : r.getRows()) {
				Time o = (Time) object;
				timesContainer.addItem(o.getTimeId(), o);
				routeTimesOptionGroup.setItemCaption(o.getTimeId(), o.getDepartureTime() +" "+ o.getAmpm());
				selectedTimes.add(o.getTimeId());
			}
		}
		if(Util.isNotEmptyResult(routeTimesResult.get("inActive"))) {
			Results r = Util.getObjectsFromXmlResult(routeTimesResult.get("inActive"), Time.class);
			for (Object object : r.getRows()) {
				Time o = (Time) object;
				timesContainer.addItem(o.getTimeId(), o);
				routeTimesOptionGroup.setItemCaption(o.getTimeId(), o.getDepartureTime() +" "+ o.getAmpm());
			}
		}
		if(Util.isNotEmptyResult(routeTimesResult.get("available"))) {
			Results r = Util.getObjectsFromXmlResult(routeTimesResult.get("available"), Time.class);
			for (Object object : r.getRows()) {
				Time o = (Time) object;
				timesContainer.addItem(o.getTimeId(), o);
				routeTimesOptionGroup.setItemCaption(o.getTimeId(), o.getDepartureTime() +" "+ o.getAmpm());
			}
		}
		
		routeTimesOptionGroup.setContainerDataSource(timesContainer);
		routeTimesOptionGroup.setValue(selectedTimes);
				
		Button close = Util.getCloseButton(window);
		
		Button save = new Button("Save");
		save.addStyleName("blueButton");
		save.setDisableOnClick(true);
		save.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	List<Time> activeTimes = new ArrayList<Time>();
		    	List<Time> inActiveTimes = new ArrayList<Time>();
		    	
		    	if(Util.isNotEmptyResult(routeTimesResult.get("RECORDS"))) 
					activeTimes = Util.getObjectsFromXmlResult(routeTimesResult.get("RECORDS"), Time.class).getRows();
					
				if(Util.isNotEmptyResult(routeTimesResult.get("inActive")))
					inActiveTimes = Util.getObjectsFromXmlResult(routeTimesResult.get("inActive"), Time.class).getRows();
					
				String setActive = "";
				Integer setActiveCounter = 0;
				String setInActive = "";
				Integer setInActiveCounter = 0;
				String createNew = "";
				Integer createNewCounter = 0;
				
				Set<Object> selectedTimes = (Set<Object>) routeTimesOptionGroup.getValue();
				for (Object object : selectedTimes) {
					Time time = ((BeanItem<Time>) routeTimesOptionGroup.getContainerDataSource().getItem(object)).getBean();
					
					if(inActiveTimes.contains(time)) { // found in the inactive list, so we have to activate it.
						if(setActiveCounter == 0)
							setActive += time.getTimeId() + Constants.itemValueSeparator + time.getTimeId();
						else
							setActive += Constants.elementSeparator + time.getTimeId() + Constants.itemValueSeparator + time.getTimeId();
						setActiveCounter++;
					} else if(! activeTimes.contains(time)) { // not in inactive and not in active list, so its a new one.
						if(createNewCounter == 0)
							createNew += time.getTimeId() + Constants.itemValueSeparator + time.getTimeId();
						else
							createNew += Constants.elementSeparator + time.getTimeId() + Constants.itemValueSeparator + time.getTimeId();
						createNewCounter++;
					}
					activeTimes.remove(time);
				}
				
				for (Time time : activeTimes) {
					if(setInActiveCounter == 0)
						setInActive += time.getTimeId() + Constants.itemValueSeparator + time.getTimeId();
					else
						setInActive += Constants.elementSeparator + time.getTimeId() + Constants.itemValueSeparator + time.getTimeId();
					setInActiveCounter++;
				}
				
				sp.param.put("setActive", setActive);
				sp.param.put("setInActive", setInActive);
				sp.param.put("createNew", createNew);
				
	    		DbServicesPrx dbServicesPrx = app.getDbServiceProxy();
	    		ServiceResult sr = dbServicesPrx.saveRouteTimes(sp);
	    		
	    		if(sr.status) {
	    			app.showNotification(Constants.MN_SUCCESSFULLY_SAVED);
	    		} else {
	    			app.showErrorNotification(sr.message);
	    			event.getButton().setEnabled(true);
	    		}
		    }
		});
		
		HorizontalLayout buttons = new HorizontalLayout();
		buttons.setSpacing(true);
		buttons.addComponent(save);
		buttons.addComponent(close);
    	
		VerticalLayout verticalLayout = (VerticalLayout) window.getContent();
		verticalLayout.setMargin(true);
        verticalLayout.setSpacing(true);
		verticalLayout.setSizeUndefined();
		verticalLayout.addComponent(routeTimesOptionGroup);
		verticalLayout.addComponent(buttons);
    	getApplication().getMainWindow().addWindow(window);
	}
	
	
	/**
	 * Creates a popup that is used to display the route details, and modify if needed. 
	 */
	private void displayRouteDetails() {
		Window window = createWindow("Route details");

		final BusApplication app = AppData.getApp();
		
		final ServiceParameter sp = new ServiceParameter(new HashMap<String, String>());
		sp.param.put("userId", AppData.getUser().getUserId().toString());
		sp.param.put("routeId", table.getValue().toString());
		sp.param.put("getAvailable", new Boolean(true).toString());
		
		Map<String, String> routeDetails = getRouteDetails(sp);
		
		SmartBeanContainer<Integer, Substation> availableSubstationsContainer = new SmartBeanContainer<Integer, Substation>(Substation.class);
		if(routeDetails.get("available") != null) {
			Results r = Util.getObjectsFromXmlResult(routeDetails.get("available"), Substation.class);
			List<Object> availableResult = r.getRows();
			for (int i = 0; i < availableResult.size(); i++) {
				Substation o = (Substation) availableResult.get(i);
				availableSubstationsContainer.addItem(i ,o);
			}
		}
		RouteDetailTable availableSubstationsTable = new RouteDetailTable("Available stations", availableSubstationsContainer, new String[] {"Substation"});
		
		SmartBeanContainer<Integer, Substation> selectedRouteSubstationsContainer = new SmartBeanContainer<Integer, Substation>(Substation.class);
		if(routeDetails.get("RECORDS") != null) {
			Results r = Util.getObjectsFromXmlResult(routeDetails.get("RECORDS"), Substation.class);
			List<Object> recordsResult = r.getRows();
			for (int i = 0; i < recordsResult.size(); i++) {
				Substation o = (Substation) recordsResult.get(i);
				selectedRouteSubstationsContainer.addItem(i, o);
			}
		}
		final RouteDetailTable selectedRouteSubstationsTable = new RouteDetailTable("Selected route stations", selectedRouteSubstationsContainer, new String[] {"Substation"});
		
		availableSubstationsTable.initializeTable(new SourceIs(selectedRouteSubstationsTable), availableSubstationsContainer);
		selectedRouteSubstationsTable.initializeTable(new SourceIs(availableSubstationsTable), selectedRouteSubstationsContainer);
		
		HorizontalLayout tablesLayout = new HorizontalLayout();
		tablesLayout.setSpacing(true);
		tablesLayout.setWidth("400px");
		tablesLayout.setHeight("400px");
		tablesLayout.addComponent(availableSubstationsTable);
		tablesLayout.addComponent(selectedRouteSubstationsTable);
		
		VerticalLayout upDownButtonsLayout = new VerticalLayout();
		upDownButtonsLayout.setSpacing(true);
		upDownButtonsLayout.addStyleName("routeDetailsUpDownButtonsLayout");
		tablesLayout.addComponent(upDownButtonsLayout);
		
		// Move To The Top button *****************************************************
        final Button moveToTopBtn = new Button("Move to top");
        moveToTopBtn.addStyleName("grayButton");
        moveToTopBtn.setDisableOnClick(true);
        moveToTopBtn.setEnabled(false);
        moveToTopBtn.addListener(new Button.ClickListener() {

            @Override
            public void buttonClick(ClickEvent event) {
            	if(selectedRouteSubstationsTable.getValue() != null) { // moving selected rows to the top of the table
	                SmartBeanContainer bc = (SmartBeanContainer)selectedRouteSubstationsTable.getContainerDataSource();
	                Set set = (Set)selectedRouteSubstationsTable.getValue();
	                int offset = bc.getMoveSpans(set)[0];
	                bc.move(set, offset);
	                event.getButton().setEnabled(true);
            	}
            }
        });
        upDownButtonsLayout.addComponent(moveToTopBtn);
		
		// Up button *****************************************************
        final Button moveUpBtn = new Button("↑");
        moveUpBtn.addStyleName("grayButton");
        moveUpBtn.setDisableOnClick(true);
        moveUpBtn.setEnabled(false);
        moveUpBtn.addListener( new Button.ClickListener() {
            @Override
            public void buttonClick(ClickEvent event) {
            	if(selectedRouteSubstationsTable.getValue() != null) { // moving selected rows 1 position up
	                SmartBeanContainer bc = (SmartBeanContainer)selectedRouteSubstationsTable.getContainerDataSource();
	                Set set = (Set)selectedRouteSubstationsTable.getValue();
	                bc.move(set, -1); // -1 = up. +1 = Down.
	                event.getButton().setEnabled(true);
            	}
            }
        });
        upDownButtonsLayout.addComponent(moveUpBtn);

        // Down button *****************************************************
        final Button moveDownBtn = new Button("↓");
        moveDownBtn.addStyleName("grayButton");
        moveDownBtn.setDisableOnClick(true);
        moveDownBtn.setEnabled(false);
        moveDownBtn.addListener( new Button.ClickListener() {
            @Override
            public void buttonClick(ClickEvent event) {
            	if(selectedRouteSubstationsTable.getValue() != null) { // moving selected rows 1 position down
	                SmartBeanContainer bc = (SmartBeanContainer)selectedRouteSubstationsTable.getContainerDataSource();
	                Set set = (Set)selectedRouteSubstationsTable.getValue();
	                bc.move(set, 1); // -1 = up. +1 = Down.
	                event.getButton().setEnabled(true);
            	}
            }
        });
        upDownButtonsLayout.addComponent(moveDownBtn);
        
     	// Move To The Bottom button *****************************************************
        final Button moveToBottomBtn = new Button("Move to bottom");
        moveToBottomBtn.addStyleName("grayButton");
        moveToBottomBtn.setDisableOnClick(true);
        moveToBottomBtn.setEnabled(false);
        moveToBottomBtn.addListener(new Button.ClickListener() {
            @Override
            public void buttonClick( ClickEvent event ) {
            	if(selectedRouteSubstationsTable.getValue() != null) { // moving selected rows to the end of the table
	                SmartBeanContainer bc = (SmartBeanContainer)selectedRouteSubstationsTable.getContainerDataSource();
	                Set set = (Set)selectedRouteSubstationsTable.getValue();
	                int offset = bc.getMoveSpans( set )[1];
	                bc.move(set, offset);
	                event.getButton().setEnabled(true);
            	}
            }
        });
        upDownButtonsLayout.addComponent(moveToBottomBtn);
        
        selectedRouteSubstationsTable.addListener(new ValueChangeListener() {
			@Override
			public void valueChange(ValueChangeEvent event) {
				if(((Set)event.getProperty().getValue()).size() > 0) { 
					// because the table values are stored in a Set, we check the size of the set
					moveToTopBtn.setEnabled(true);
					moveUpBtn.setEnabled(true);
					moveDownBtn.setEnabled(true);
					moveToBottomBtn.setEnabled(true);
				} else {
					moveToTopBtn.setEnabled(false);
					moveUpBtn.setEnabled(false);
					moveDownBtn.setEnabled(false);
					moveToBottomBtn.setEnabled(false);
				}
			}
		});
		
		Button close = Util.getCloseButton(window);
		close.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	if(isSaved)
		    		loadRouteData();
		    }
		});
		
		Button save = new Button("Save");
		save.addStyleName("blueButton");
		save.setDisableOnClick(true);
		save.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	Map<String, String> routeDetails = getRouteDetails(sp);
		    	SmartBeanContainer selectedSubstations = (SmartBeanContainer) selectedRouteSubstationsTable.getContainerDataSource();
		    	
		    	String newRouteDetails = "";
				List<Object> ids = selectedSubstations.getAllItemIds();
				int j = 1;
				for (Object id : ids) {
					Substation p = ((BeanItem<Substation>) selectedSubstations.getItem(id)).getBean();
					if(j == 1)
						newRouteDetails += j + Constants.itemValueSeparator + p.getSubstationId();
					else
						newRouteDetails += Constants.elementSeparator + j + Constants.itemValueSeparator + p.getSubstationId();
					j++;
				}
				
				sp.param.put("routeDetails", newRouteDetails);
		    	
	    		DbServicesPrx dbServicesPrx = app.getDbServiceProxy();
	    		ServiceResult sr = dbServicesPrx.saveRouteDetails(sp);
	    		
	    		if(sr.status) {
	    			app.showNotification(Constants.MN_SUCCESSFULLY_SAVED);
	    			isSaved = true;
	    		} else {
	    			app.showErrorNotification(sr.message);
	    			event.getButton().setEnabled(true);
	    			isSaved = false;
	    		}
		    }
		});
		
		HorizontalLayout buttons = new HorizontalLayout();
		buttons.setSpacing(true);
		buttons.addComponent(save);
		buttons.addComponent(close);
    	
		VerticalLayout verticalLayout = (VerticalLayout) window.getContent();
		verticalLayout.setMargin(true);
        verticalLayout.setSpacing(true);
		verticalLayout.setSizeUndefined();
		verticalLayout.addComponent(tablesLayout);
		verticalLayout.addComponent(buttons);
    	getApplication().getMainWindow().addWindow(window);
	}
	
	/**
	 * Gets for the selected route the rout details.
	 * 
	 * @param sp, should contain: <br/>
	 * <ul>
	 *		<li> userId, required </li>
	 *		<li> routeId, required </li>
	 *		<li> getAvailable </li>
	 * </ul>
	 * 
	 * @return Map<String, String>
	 */
	private Map<String, String> getRouteDetails(ServiceParameter sp) {
		Map<String, String> result = null;
		BusApplication app = AppData.getApp();
		
		DbServicesPrx dbServicesPrx = app.getDbServiceProxy();
		ServiceResult sr = dbServicesPrx.getRouteDetails(sp);
		
		if(sr.status) {
			result = sr.param;
		} else {
			app.showErrorNotification(sr.message);
		}
		
		return result;
	}
	
	/**
	 * Gets for the selected route the times.
	 * 
	 * @param sp, should contain: <br/>
	 * <ul>
	 *		<li> userId, required </li>
	 *		<li> routeId, required </li>
	 *		<li> getAvailable </li>
	 * </ul>
	 * 
	 * @return Map<String, String>
	 */
	private Map<String, String> getRouteTimes(ServiceParameter sp) {
		Map<String, String> result = null;
		BusApplication app = AppData.getApp();
		
		DbServicesPrx dbServicesPrx = app.getDbServiceProxy();
		ServiceResult sr = dbServicesPrx.getRouteTimes(sp);
		
		if(sr.status) {
			result = sr.param;
		} else {
			app.showErrorNotification(sr.message);
		}
		
		return result;
	}
	
	/**
	 * <p> <code>RouteDetailTable</code> is used for representing route details in a table.</p>
	 * 
	 * @author Abdullahi
	 *
	 */
	private class RouteDetailTable extends Table {

		public RouteDetailTable(String caption, Container containers, String [] columns) {
			super(caption, containers);
			
			addGeneratedColumn("Substation", new ColumnGenerator() {
			  public Component generateCell(Table source, Object itemId,
			            Object columnId) {
			      if (getItem(itemId).getItemProperty("name").getValue() != null) {
			          Label l = new Label();
			          l.setValue(getItem(itemId).getItemProperty("name").getValue());
			          l.setSizeUndefined();
			          return l;
			      }
			      return null;
			  }
			});
			
			addStyleName(Runo.TABLE_SMALL);
			setVisibleColumns(columns);
			setSizeUndefined();
			setSelectable(true);
			setMultiSelect(true);
			setMultiSelectMode(MultiSelectMode.SIMPLE);
			setImmediate(true);
		}
		
		public void initializeTable(final ClientSideCriterion acceptCriterion, final BeanContainer<Integer, Substation> tableContainer) {

			// Handle drop in table: item or subtree to the table
	        setDragMode(TableDragMode.MULTIROW);
	        setSizeFull();
	        setDropHandler(new DropHandler() {
	            public void drop(DragAndDropEvent dropEvent) {
	            	// criteria verify that this is safe
	                DataBoundTransferable dataBound = (DataBoundTransferable) dropEvent.getTransferable();
	                Container sourceContainer = dataBound.getSourceContainer();
	                //RouteDetailTable desestination = (RouteDetailTable) dropEvent.getTargetDetails().getTarget();
	                RouteDetailTable source = (RouteDetailTable) dataBound.getSourceComponent();
	                Set<Integer> selectedValues =  (Set<Integer>) source.getValue();
	                source.setValue(null);
	                for (Integer i : selectedValues) {
	                	Substation sub = ((BeanItem<Substation>) source.getContainerDataSource().getItem(i)).getBean();
		                tableContainer.addItem(tableContainer.size(), sub);
		                sourceContainer.removeItem(i);
	                }
	            }

	            public AcceptCriterion getAcceptCriterion() {
	                return new And(acceptCriterion, AcceptItem.ALL);
	            }
	        });
	    }
	}
	
	/**
	 * Displays a popup to add a new route.
	 */
	private void displayAddRoute(String description) {
		Window window = createWindow("Add "+ description);

		BusApplication app = AppData.getApp();
		
		final BeanContainer<Integer, Substation> container = new BeanContainer<Integer, Substation>(Substation.class);
		container.setBeanIdProperty("substationId");
		
		ServiceParameter sp = new ServiceParameter(new HashMap<String, String>());
		
		DbServicesPrx dbServicesPrx = app.getDbServiceProxy();
		ServiceResult sr = dbServicesPrx.getAllSubstations(sp);
		if(sr.status) {
			if(sr.param.get("RECORDS") != null) {
				Results r = Util.getObjectsFromXmlResult(sr.param.get("RECORDS"), Substation.class);
				
				for (Object object : r.getRows()) {
					Substation substation = (Substation) object;
					container.addItem(substation.getSubstationId(), substation);
				}
			}
		} else {
			app.showErrorNotification(sr.message);
		}
		
		final Form form = new Form();
    	form.setWidth("500px");
		form.setFormFieldFactory(new FormFieldFactory() {
			
			@Override
			public Field createField(Item item, Object propertyId, Component uiContext) {
				Field f = null;
				
				if ("routeStartId".equals(propertyId)) {
					ComboBox field = new ComboBox("Route start");
					field.focus();
					field.setRequired(true);
					field.setImmediate(true);
					field.setWidth(Constants.COMMON_FIELD_WIDTH_M);
					field.setRequiredError(Constants.ME_FIELDS_REQUIRED);
					field.setNullSelectionAllowed(false);
					field.setContainerDataSource(container);
					field.setItemCaptionPropertyId("name");
					return field;
				} if ("routeEndId".equals(propertyId)) {
					ComboBox field = new ComboBox("Route end");
					field.setRequired(true);
					field.setImmediate(true);
					field.setWidth(Constants.COMMON_FIELD_WIDTH_M);
					field.setRequiredError(Constants.ME_FIELDS_REQUIRED);
					field.setNullSelectionAllowed(false);
					field.setContainerDataSource(container);
					field.setItemCaptionPropertyId("name");
					return field;
				} if ("routeStatusId".equals(propertyId)) {
					ComboBox field = new ComboBox("Status");
					field.setRequired(true);
					field.setImmediate(true);
					field.setWidth(Constants.COMMON_FIELD_WIDTH_M);
					field.setRequiredError(Constants.ME_FIELDS_REQUIRED);
					field.setNullSelectionAllowed(false);
					
					BeanContainer<Integer, Temp> cont = new BeanContainer<Integer, Temp>(Temp.class);
					cont.addItem(1, new Temp(1, "Active"));
					cont.addItem(2, new Temp(2, "Inactive"));
					field.setContainerDataSource(cont);
					field.setItemCaptionPropertyId("description");
					return field;
				} 
				return f;
			}
		});
		form.setItemDataSource(new BeanItem<Route>(new Route()));
		form.setVisibleItemProperties(Constants.columnsRouteAddForm);
		
		Button close = Util.getCloseButton(window);
		close.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	if(isSaved)
		    		loadRouteData();
		    }
		});
		
		Button save = new Button("Save");
		save.addStyleName("blueButton");
		save.setDisableOnClick(true);
		save.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	BusApplication app = (BusApplication) getApplication();
		    	if(form.isValid()) {
		    		String start = form.getField("routeStartId").getValue().toString();
		    		String end = form.getField("routeEndId").getValue().toString();
		    		if(start.equalsIgnoreCase(end)) {
		    			app.showErrorNotification(Constants.ME_FROM_TO_SUBSTATIONS_ARE_THE_SAME);
		    			event.getButton().setEnabled(true);
		    		} else {
			    		ServiceParameter sp = new ServiceParameter(new HashMap<String, String>());
			    		sp.param.put("userId", AppData.getUser().getUserId().toString());
			    		sp.param.put("routeStart", start);
			    		sp.param.put("routeEnd", end);
			    		sp.param.put("routeStatus", form.getField("routeStatusId").getValue().toString());
			    		
			    		DbServicesPrx dbServicesPrx = app.getDbServiceProxy();
			    		ServiceResult sr = dbServicesPrx.addRoute(sp);
			    		
			    		if(sr.status) {
			    			form.setReadOnly(true);
			    			app.showNotification(Constants.MN_SUCCESSFULLY_SAVED);
			    			event.getButton().setEnabled(false);
			    			isSaved = true;
			    		} else {
			    			app.showErrorNotification(sr.message);
			    			event.getButton().setEnabled(true);
			    			isSaved = false;
			    		}
		    		}
		    	} else {
		    		app.showErrorNotification(Constants.ME_FORM_FIELDS_REQUIRED);
		    		event.getButton().setEnabled(true);
		    	}
		    }
		});
		
		HorizontalLayout buttons = new HorizontalLayout();
		buttons.setSpacing(true);
		buttons.addComponent(save);
		buttons.addComponent(close);
    	
		VerticalLayout verticalLayout = (VerticalLayout) window.getContent();
		verticalLayout.setMargin(true);
        verticalLayout.setSpacing(true);
		verticalLayout.setSizeUndefined();
		verticalLayout.addComponent(form);
		verticalLayout.addComponent(buttons);
    	getApplication().getMainWindow().addWindow(window);
	}
	
	/**
	 * Displays a popup to edit the selected route.
	 */
	private void displayEditRoute(String description) {
		Window window = createWindow("Edit "+ description);
    	
		final Form form = new Form();
    	form.setWidth("500px");
		form.setFormFieldFactory(new FormFieldFactory() {
			
			@Override
			public Field createField(Item item, Object propertyId, Component uiContext) {
				Field f = null;
				if ("routeId".equals(propertyId)) {
					TextField field = new TextField("Route id");
					field.setRequired(true);
					field.setImmediate(true);
					field.setWidth(Constants.COMMON_FIELD_WIDTH_M);
					field.setRequiredError(Constants.ME_FIELDS_REQUIRED);
					field.setNullRepresentation("");
					field.setReadOnly(true);
					return field;
				} if ("routeStatusId".equals(propertyId)) {
					ComboBox field = new ComboBox("Status");
					field.focus();
					field.setRequired(true);
					field.setImmediate(true);
					field.setWidth(Constants.COMMON_FIELD_WIDTH_M);
					field.setRequiredError(Constants.ME_FIELDS_REQUIRED);
					field.setNullSelectionAllowed(false);
					
					BeanContainer<Integer, Temp> cont = new BeanContainer<Integer, Temp>(Temp.class);
					cont.addItem(1, new Temp(1, "Active"));
					cont.addItem(2, new Temp(2, "Inactive"));
					field.setContainerDataSource(cont);
					field.setItemCaptionPropertyId("description");
					return field;
				}  
				return f;
			}
		});
		form.setItemDataSource(table.getItem(table.getValue()));
		form.setVisibleItemProperties(Constants.columnsRouteEditForm);
		
		Button close = Util.getCloseButton(window);
		close.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	if(isSaved)
		    		loadRouteData();
		    }
		});
		
		Button save = new Button("Save");
		save.addStyleName("blueButton");
		save.setDisableOnClick(true);
		save.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	BusApplication app = (BusApplication) getApplication();
		    	if(form.isValid()) {
		    		ServiceParameter sp = new ServiceParameter(new HashMap<String, String>());
		    		sp.param.put("userId", AppData.getUser().getUserId().toString());
		    		sp.param.put("routeId", form.getField("routeId").getValue().toString());
		    		sp.param.put("routeStatus", form.getField("routeStatusId").getValue().toString());
		    		
		    		DbServicesPrx dbServicesPrx = app.getDbServiceProxy();
		    		ServiceResult sr = dbServicesPrx.editRoute(sp);
		    		
		    		if(sr.status) {
		    			form.setReadOnly(true);
		    			app.showNotification(Constants.MN_SUCCESSFULLY_SAVED);
		    			event.getButton().setEnabled(false);
		    			isSaved = true;
		    		} else {
		    			app.showErrorNotification(sr.message);
		    			event.getButton().setEnabled(true);
		    			isSaved = false;
		    		}
		    	} else {
		    		app.showErrorNotification(Constants.ME_FORM_FIELDS_REQUIRED);
		    		event.getButton().setEnabled(true);
		    	}
		    }
		});
		
		HorizontalLayout buttons = new HorizontalLayout();
		buttons.setSpacing(true);
		buttons.addComponent(save);
		buttons.addComponent(close);
    	
		VerticalLayout verticalLayout = (VerticalLayout) window.getContent();
		verticalLayout.setMargin(true);
        verticalLayout.setSpacing(true);
		verticalLayout.setSizeUndefined();
		verticalLayout.addComponent(form);
		verticalLayout.addComponent(buttons);
    	getApplication().getMainWindow().addWindow(window);
	}
	
	/**
	 * Displays the data from seat table in a table view.
	 */
	private void loadSeatData() {
		BusApplication app = AppData.getApp();
		ServiceParameter sp = new ServiceParameter(new HashMap<String, String>());
		
		BeanContainer<Integer, Seat> container = new BeanContainer<Integer, Seat>(Seat.class);
		container.setBeanIdProperty("seatId");
		
		DbServicesPrx dbServicesPrx = app.getDbServiceProxy();
		ServiceResult sr = dbServicesPrx.getSeats(sp);
		if(sr.status) {
			if(sr.param.get("RECORDS") != null) {
				Results r = Util.getObjectsFromXmlResult(sr.param.get("RECORDS"), Seat.class);
				for (Object object : r.getRows()) {
					Seat o = (Seat) object;
					container.addItem(o.getSeatId(), o);
				}
				table.setContainerDataSource(container);
				table.setVisible(true);
				actionButtons.setVisible(true);
				table.setVisibleColumns(Constants.columnsSeatTable);
			} else {
				table.setContainerDataSource(null);
				table.setVisible(false);
				actionButtons.setVisible(false);
			}
		} else {
			app.showErrorNotification(sr.message);
			table.setContainerDataSource(null);
			table.setVisible(false);
			actionButtons.setVisible(false);
		}
	}
	
	/**
	 * Displays a popup to add a new seat.
	 */
	private void displayAddSeat(String description) {
		Window window = createWindow("Add "+ description);
    	
		final Form form = new Form();
    	form.setWidth("500px");
		form.setFormFieldFactory(new FormFieldFactory() {
			
			@Override
			public Field createField(Item item, Object propertyId, Component uiContext) {
				Field f = null;
				if ("description".equals(propertyId)) {
					TextField field = new TextField("Description");
					field.focus();
					field.setRequired(true);
					field.setImmediate(true);
					field.setWidth(Constants.COMMON_FIELD_WIDTH_M);
					field.setRequiredError(Constants.ME_FIELDS_REQUIRED);
					field.addValidator(new StringLengthValidator(Constants.ME_BETWEEN_2_AND_3_CHARS_ALLOWED, 2, 3, false));
					field.setNullRepresentation("");
					return field;
				}
				return f;
			}
		});
		form.setItemDataSource(new BeanItem<Seat>(new Seat()));
		form.setVisibleItemProperties(Constants.columnsSeatForm);
		
		Button close = Util.getCloseButton(window);
		close.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	if(isSaved)
		    		loadSeatData();
		    }
		});
		
		Button save = new Button("Save");
		save.addStyleName("blueButton");
		save.setDisableOnClick(true);
		save.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	BusApplication app = (BusApplication) getApplication();
		    	if(form.isValid()) {
		    		ServiceParameter sp = new ServiceParameter(new HashMap<String, String>());
		    		sp.param.put("userId", AppData.getUser().getUserId().toString());
		    		sp.param.put("description", form.getField("description").getValue().toString());
		    		
		    		DbServicesPrx dbServicesPrx = app.getDbServiceProxy();
		    		ServiceResult sr = dbServicesPrx.addSeat(sp);
		    		
		    		if(sr.status) {
		    			form.setReadOnly(true);
		    			app.showNotification(Constants.MN_SUCCESSFULLY_SAVED);
		    			event.getButton().setEnabled(false);
		    			isSaved = true;
		    		} else {
		    			app.showErrorNotification(sr.message);
		    			event.getButton().setEnabled(true);
		    			isSaved = false;
		    		}
		    	} else {
		    		app.showErrorNotification(Constants.ME_FORM_FIELDS_REQUIRED);
		    		event.getButton().setEnabled(true);
		    	}
		    }
		});
		
		HorizontalLayout buttons = new HorizontalLayout();
		buttons.setSpacing(true);
		buttons.addComponent(save);
		buttons.addComponent(close);
    	
		VerticalLayout verticalLayout = (VerticalLayout) window.getContent();
		verticalLayout.setMargin(true);
        verticalLayout.setSpacing(true);
		verticalLayout.setSizeUndefined();
		verticalLayout.addComponent(form);
		verticalLayout.addComponent(buttons);
    	getApplication().getMainWindow().addWindow(window);
	}
	
	/**
	 * Displays a popup to edit the selected seat.
	 */
	private void displayEditSeat(String description) {
		Window window = createWindow("Edit "+ description);
    	
		final Form form = new Form();
    	form.setWidth("500px");
		form.setFormFieldFactory(new FormFieldFactory() {
			
			@Override
			public Field createField(Item item, Object propertyId, Component uiContext) {
				Field f = null;
				if ("seatId".equals(propertyId)) {
					TextField field = new TextField("Seat id");
					field.setRequired(true);
					field.setImmediate(true);
					field.setWidth(Constants.COMMON_FIELD_WIDTH_M);
					field.setRequiredError(Constants.ME_FIELDS_REQUIRED);
					field.setNullRepresentation("");
					field.setReadOnly(true);
					return field;
				} if ("description".equals(propertyId)) {
					TextField field = new TextField("Description");
					field.focus();
					field.setRequired(true);
					field.setImmediate(true);
					field.setWidth(Constants.COMMON_FIELD_WIDTH_M);
					field.setRequiredError(Constants.ME_FIELDS_REQUIRED);
					field.setNullRepresentation("");
					field.addValidator(new StringLengthValidator(Constants.ME_BETWEEN_2_AND_3_CHARS_ALLOWED, 2, 3, false));
					return field;
				}
				return f;
			}
		});
		form.setItemDataSource(table.getItem(table.getValue()));
		form.setVisibleItemProperties(Constants.columnsSeatTable);
		
		Button close = Util.getCloseButton(window);
		close.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	if(isSaved)
		    		loadSeatData();
		    }
		});
		
		Button save = new Button("Save");
		save.addStyleName("blueButton");
		save.setDisableOnClick(true);
		save.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	BusApplication app = (BusApplication) getApplication();
		    	if(form.isValid()) {
		    		ServiceParameter sp = new ServiceParameter(new HashMap<String, String>());
		    		sp.param.put("userId", AppData.getUser().getUserId().toString());
		    		sp.param.put("seatId", form.getField("seatId").getValue().toString());
		    		sp.param.put("description", form.getField("description").getValue().toString());
		    		
		    		DbServicesPrx dbServicesPrx = app.getDbServiceProxy();
		    		ServiceResult sr = dbServicesPrx.editSeat(sp);
		    		
		    		if(sr.status) {
		    			form.setReadOnly(true);
		    			app.showNotification(Constants.MN_SUCCESSFULLY_SAVED);
		    			isSaved = true;
		    		} else {
		    			app.showErrorNotification(sr.message);
		    			event.getButton().setEnabled(true);
		    			isSaved = false;
		    		}
		    	} else {
		    		app.showErrorNotification(Constants.ME_FORM_FIELDS_REQUIRED);
		    		event.getButton().setEnabled(true);
		    	}
		    }
		});
		
		HorizontalLayout buttons = new HorizontalLayout();
		buttons.setSpacing(true);
		buttons.addComponent(save);
		buttons.addComponent(close);
    	
		VerticalLayout verticalLayout = (VerticalLayout) window.getContent();
		verticalLayout.setMargin(true);
        verticalLayout.setSpacing(true);
		verticalLayout.setSizeUndefined();
		verticalLayout.addComponent(form);
		verticalLayout.addComponent(buttons);
    	getApplication().getMainWindow().addWindow(window);
	}
}
